package com.xue;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.pi4j.util.StringUtil;
import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;

import javax.swing.text.Position;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author xuejingbao
 * @create 2023-10-16 下午 14:41
 */
public class MqttLocation {

    private static class MqttLocationHolder {
        private static final MqttLocation INSTANCE = new MqttLocation();
    }

    private MqttLocation() {
    }

    public static MqttLocation getInstance() {
        return MqttLocationHolder.INSTANCE;
    }

    private static final Integer CONNECTION_TIMEOUT = 10;
    private static final Integer KEEPALIVE_INTERVAL = 20;
    private static final Integer QOS = 1;
    private GpsForPi gpsForPi = GpsForPi.getInstance();
    private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HHmmss");
    private static final DateTimeFormatter SHORT_DATE_FORMATTER = DateTimeFormatter.ofPattern("ddMMyy");

    public void init() {
        try {
            MqttClient mqttClient = new MqttClient(Config.INSTANCE.getHost(), Config.INSTANCE.getClientId(), new MemoryPersistence());
            // MQTT的连接设置
            MqttConnectOptions options = new MqttConnectOptions();
            // 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录，这里设置为true表示每次连接到服务器都以新的身份连接
            options.setCleanSession(true);
            // 设置连接的用户名
            options.setUserName(Config.INSTANCE.getUserName());
            // 设置连接的密码
            options.setPassword(Config.INSTANCE.getPassword().toCharArray());
            // 设置超时时间 单位为秒
            options.setConnectionTimeout(CONNECTION_TIMEOUT);
            // 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线，但这个方法并没有重连的机制
            options.setKeepAliveInterval(KEEPALIVE_INTERVAL);
            // 设置回调函数

            mqttClient.setCallback(new MqttCallback() {
                @Override
                public void connectionLost(Throwable cause) {
                    System.out.println("Mqtt Lost");
                }

                @Override
                public void messageArrived(String topic, MqttMessage message) throws Exception {
                    String msg = new String(message.getPayload());
                    JSONObject json = JSONUtil.parseObj(msg);
                    Double lon = json.getDouble("lon");
                    Double lat = json.getDouble("lat");
                    LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC);
                    String str = StrUtil.format("$GPRMC,{}.00,A,{},N,{},E,0.0,225.5,{},2.3,W,A*23\r\n",
                            now.format(TIME_FORMATTER), convert(lat), convert(lon), now.format(SHORT_DATE_FORMATTER));
                    System.out.println(StrUtil.format("mqtt message == lon:{},lat:{},send gps:\n{}",
                            lon, lat, str));
                    gpsForPi.sendMessage(str.getBytes(StandardCharsets.US_ASCII));
                }

                @Override
                public void deliveryComplete(IMqttDeliveryToken token) {
                    System.out.println("Mqtt Message Complete");
                }

            });

            mqttClient.connect(options);
            //订阅消息
            mqttClient.subscribe(Config.INSTANCE.getTopic(), QOS);
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    private static String convert(double decimalDegrees) {
        // 计算度数
        int degrees = (int) decimalDegrees;

        // 计算分钟
        double decimalMinutes = (decimalDegrees - degrees) * 60.0;
        int minutes = (int) decimalMinutes;

        // 格式化结果为度和分钟（ddmm.mmmm）
        return String.format("%02d%06.4f", degrees, decimalMinutes);
    }

    public void testSend() {
        ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
        ses.scheduleAtFixedRate(() -> {
            LocalDateTime now = LocalDateTime.now(ZoneOffset.UTC);
            String time = now.format(TIME_FORMATTER);
            String dateTime = now.format(SHORT_DATE_FORMATTER);
            String latStr = convert(30.233612);
            String lonStr = convert(119.720662);


            String str1 = "$GNRMC,"+time+".00,A,3015.77550,N,11953.38705,E,0.012,,"+dateTime+",,,A*6E\r\n";
            String str2 = "$GNVTG,,T,,M,0.012,N,0.023,K,A*3F\r\n";
            String str3 = "$GNGGA,"+time+".00,3015.77550,N,11953.38705,E,1,11,1.06,50.8,M,6.6,M,,*4D\r\n";
            String str4 = "$GNGSA,A,3,32,25,28,10,31,12,29,,,,,,1.67,1.06,1.28*17\r\n";
            String str5 = "$GNGSA,A,3,65,75,72,66,,,,,,,,,1.67,1.06,1.28*14\r\n";
            String str6 = "$GPGSV,3,1,10,10,49,191,37,12,18,041,21,23,,,34,25,56,058,44*48\r\n";
            String str7 = "$GPGSV,3,2,10,26,22,210,,28,54,302,44,29,13,122,17,31,35,272,32*78\r\n";
            String str8 = "$GPGSV,3,3,10,32,68,011,47,50,54,166,37*75\r\n";
            String str9 = "$GLGSV,2,1,08,65,70,359,44,66,18,329,19,72,44,127,41,74,12,033,*68\r\n";
            String str10 = "$GLGSV,2,2,08,75,63,008,46,76,48,233,30,77,03,221,,,,,44*5E\r\n";
            String str11 = "$GNGLL,3015.77550,N,11953.38705,E,"+time+".00,A,A*72\r\n";
            gpsForPi.sendMessage(str1.getBytes(StandardCharsets.UTF_8));
            gpsForPi.sendMessage(str2.getBytes(StandardCharsets.UTF_8));
            gpsForPi.sendMessage(str3.getBytes(StandardCharsets.UTF_8));
            gpsForPi.sendMessage(str4.getBytes(StandardCharsets.UTF_8));
            gpsForPi.sendMessage(str5.getBytes(StandardCharsets.UTF_8));
            gpsForPi.sendMessage(str6.getBytes(StandardCharsets.UTF_8));
            gpsForPi.sendMessage(str7.getBytes(StandardCharsets.UTF_8));
            gpsForPi.sendMessage(str8.getBytes(StandardCharsets.UTF_8));
            gpsForPi.sendMessage(str9.getBytes(StandardCharsets.UTF_8));
            gpsForPi.sendMessage(str10.getBytes(StandardCharsets.UTF_8));
            gpsForPi.sendMessage(str11.getBytes(StandardCharsets.UTF_8));
        }, 1, 1, TimeUnit.SECONDS);
    }

}
